package com.eian.boot.module.system.dept.service;

import com.eian.boot.common.core.exception.ExceptionHelper;
import com.eian.boot.common.core.utils.BeanCopierUtils;
import com.eian.boot.module.system.dept.mapper.SysDeptMapper;
import com.eian.boot.module.system.dept.model.dto.DeptCreateRequest;
import com.eian.boot.module.system.dept.model.dto.DeptUpdateRequest;
import com.eian.boot.module.system.dept.model.entity.SysDeptEntity;
import com.eian.boot.module.system.dept.model.vo.DeptTreeVO;
import com.eian.boot.mybatis.core.service.BaseService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.eian.boot.table.Tables.sys_dept;

/**
 * 系统部门服务
 *
 * @author alex.meng
 * @since 1.0.0
 */
@Service
@AllArgsConstructor
public class SysDeptService extends BaseService<SysDeptMapper, SysDeptEntity> {

    /**
     * 创建部门
     */
    @Transactional(rollbackFor = Exception.class)
    public void createDept(DeptCreateRequest request) {
        // 检查部门编码是否重复
        boolean exists = this.queryChain()
                .where(sys_dept.dept_code.eq(request.getDeptCode()))
                .exists();
        ExceptionHelper.ifTrue(exists, "部门编码已存在");

        // 检查父部门是否存在
        SysDeptEntity parentDept = null;
        if (request.getParentId() != null && request.getParentId() > 0) {
            parentDept = this.getById(request.getParentId());
            ExceptionHelper.ifNull(parentDept, "父部门不存在");
        }

        SysDeptEntity dept = BeanCopierUtils.copy(request, SysDeptEntity.class);

        // 构建ancestors
        if (parentDept != null) {
            dept.setAncestors(parentDept.getAncestors() + "," + parentDept.getId());
        } else {
            dept.setAncestors("0");
        }

        this.save(dept);
    }

    /**
     * 获取部门树
     */
    public List<DeptTreeVO> getDeptTree() {
        List<SysDeptEntity> allDepts = this.queryChain()
                .orderBy(SysDeptEntity::getSortOrder).asc()
                .orderBy(SysDeptEntity::getId).asc()
                .list();

        List<DeptTreeVO> deptVOList = BeanCopierUtils.copyList(allDepts, DeptTreeVO.class);
        return buildDeptTree(deptVOList, 0L);
    }

    /**
     * 构建部门树
     */
    private List<DeptTreeVO> buildDeptTree(List<DeptTreeVO> allDepts, Long parentId) {
        List<DeptTreeVO> result = new ArrayList<>();

        Map<Long, List<DeptTreeVO>> deptGroup = allDepts.stream()
                .collect(Collectors.groupingBy(d -> d.getParentId() == null ? 0L : d.getParentId()));

        List<DeptTreeVO> currentLevel = deptGroup.get(parentId);
        if (currentLevel != null) {
            for (DeptTreeVO dept : currentLevel) {
                List<DeptTreeVO> children = buildDeptTree(allDepts, dept.getId());
                dept.setChildren(children);
                result.add(dept);
            }
        }

        return result;
    }

    /**
     * 获取部门详情
     */
    public DeptTreeVO getDeptDetail(Long id) {
        SysDeptEntity dept = this.getById(id);
        ExceptionHelper.ifNull(dept, "部门不存在");
        return BeanCopierUtils.copy(dept, DeptTreeVO.class);
    }

    /**
     * 更新部门
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDept(DeptUpdateRequest request) {
        SysDeptEntity dept = this.getById(request.getId());
        ExceptionHelper.ifNull(dept, "部门不存在");

        // 检查部门编码是否重复
        if (StringUtils.isNotBlank(request.getDeptCode()) && !request.getDeptCode().equals(dept.getDeptCode())) {
            boolean exists = this.queryChain()
                    .where(sys_dept.dept_code.eq(request.getDeptCode()))
                    .and(sys_dept.id.ne(request.getId()))
                    .exists();
            ExceptionHelper.ifTrue(exists, "部门编码已存在");
        }

        // 更新部门信息
        BeanCopierUtils.copy(request, dept);

        // 如果修改了父部门，需要更新ancestors
        if (request.getParentId() != null && !request.getParentId().equals(dept.getParentId())) {
            updateDeptAncestors(dept, request.getParentId());
        }

        this.updateById(dept);
    }

    /**
     * 更新部门祖先路径
     */
    private void updateDeptAncestors(SysDeptEntity dept, Long newParentId) {
        String newAncestors;
        if (newParentId == null || newParentId == 0) {
            newAncestors = "0";
        } else {
            SysDeptEntity parentDept = this.getById(newParentId);
            ExceptionHelper.ifNull(parentDept, "父部门不存在");
            newAncestors = parentDept.getAncestors() + "," + parentDept.getId();
        }
        dept.setAncestors(newAncestors);
        dept.setParentId(newParentId);
    }

    /**
     * 删除部门
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDept(Long id) {
        SysDeptEntity dept = this.getById(id);
        ExceptionHelper.ifNull(dept, "部门不存在");

        // 检查是否有子部门
        long childCount = this.queryChain()
                .where(sys_dept.parent_id.eq(id))
                .count();
        ExceptionHelper.ifTrue(childCount > 0, "存在子部门，无法删除");

        this.removeById(id);
    }

    /**
     * 获取部门及所有子部门ID
     */
    public List<Long> getDeptAndChildrenIds(Long deptId) {
        SysDeptEntity dept = this.getById(deptId);
        if (dept == null) {
            return new ArrayList<>();
        }

        String pattern = dept.getAncestors() + "," + deptId;

        List<Long> deptIds = this.queryChain()
                .select(sys_dept.id)
                .where(sys_dept.id.eq(deptId)
                        .or(sys_dept.ancestors.like(pattern + ",%"))
                        .or(sys_dept.ancestors.eq(pattern)))
                .listAs(Long.class);

        return deptIds;
    }
}

